package foodmaterial.service.impl;

import com.github.pagehelper.PageHelper;
import foodmaterial.action.FoodMaterialAction;
import foodmaterial.dao.FoodMaterialDao;
import foodmaterial.dto.*;
import foodmaterial.entity.*;
import foodmaterial.service.FoodMaterialService;
import foodmaterial.utils.Constants;
import foodmaterial.utils.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

@Service
public class FoodMaterialServiceImpl extends BaseService implements FoodMaterialService {

    @Autowired
    private FoodMaterialDao dao ;

    private String checkFoodMaterialType(FoodMaterialType foodMaterialType) {
        FoodMaterialTypeDto fmt = new FoodMaterialTypeDto() ;
        fmt.setName(foodMaterialType.getName());
        List<FoodMaterialType> list = dao.selectFoodMaterialType(fmt) ;
        return checkExist(list,foodMaterialType) ;
    }

    @Override
    //@CacheEvict(cacheNames={FOOD_MATERIAL_TYPE_CACHE},key = "#foodMaterialType.db")
    public String addFoodMaterialType(FoodMaterialType foodMaterialType) {
        String result = checkFoodMaterialType(foodMaterialType) ;
        if (result != null) return result ;
        foodMaterialType.setId(nextId());
        int row = dao.insertFoodMaterialType(foodMaterialType);
        if (row <= 0) return "新增食材分类失败" ;
        return null ;
    }

    @Override
    //@CacheEvict(cacheNames={FOOD_MATERIAL_TYPE_CACHE},key = "#foodMaterialType.db")
    public String modifyFoodMaterialType(FoodMaterialType foodMaterialType) {
        String result = checkFoodMaterialType(foodMaterialType) ;
        if (result != null) return result ;
        int row = dao.updateFoodMaterialType(foodMaterialType);
        if (row <= 0) return "没有此食材分类信息" ;
        return null ;
    }

    @Override
    public List<FoodMaterialType> queryFoodMaterialType(FoodMaterialTypeDto dto) {
        return dao.selectFoodMaterialType(dto);
    }

    @Override
    //@Cacheable(cacheNames={FOOD_MATERIAL_TYPE_CACHE},key="#db")
    public List<FoodMaterialType> queryFoodMaterialType(String db) {
        FoodMaterialTypeDto dto = new FoodMaterialTypeDto() ;
        return dao.selectFoodMaterialType(dto);
    }

    private String checkFoodMaterialUnit(FoodMaterialUnit foodMaterialUnit) {
        FoodMaterialUnit fmu = new FoodMaterialUnit() ;
        fmu.setName(foodMaterialUnit.getName());
        List<FoodMaterialUnit> list = dao.selectFoodMaterialUnit(fmu) ;
        return checkExist(list,foodMaterialUnit) ;
    }

    @Override
    public String addFoodMaterialUnit(FoodMaterialUnit foodMaterialUnit) {
        String result = checkFoodMaterialUnit(foodMaterialUnit) ;
        if (result != null) return result ;
        foodMaterialUnit.setId(nextId());
        int row = dao.insertFoodMaterialUnit(foodMaterialUnit);
        if (row <= 0) return "新增计量单位失败" ;
        return null ;
    }

    @Override
    public String modifyFoodMaterialUnit(FoodMaterialUnit foodMaterialUnit) {
        String result = checkFoodMaterialUnit(foodMaterialUnit) ;
        if (result != null) return result ;
        int row = dao.updateFoodMaterialUnit(foodMaterialUnit);
        if (row <= 0) return "修改计量单位失败" ;
        return null ;
    }

    @Override
    public List<FoodMaterialUnit> queryFoodMaterialUnit(FoodMaterialUnit foodMaterialUnit) {
        return dao.selectFoodMaterialUnit(foodMaterialUnit);
    }

    private String checkFoodMaterialName(FoodMaterial foodMaterial) {
        FoodMaterialDto fm = new FoodMaterialDto() ;
        fm.setName(foodMaterial.getName());
        fm.setOriginalProcess(foodMaterial.getOriginalProcess());
        List<FoodMaterial> list = dao.selectFoodMaterial(fm) ;
        return checkExist(list,foodMaterial) ;
    }

    @Override
    public String addFoodMaterial(FoodMaterial foodMaterial) {
        String result = checkFoodMaterialName(foodMaterial) ;
        if (result != null) return result ;
        foodMaterial.setId(nextId());
        if (foodMaterial.getOriginalProcess() == false) foodMaterial.setOriginalType(foodMaterial.getId());
        int rows = dao.insertFoodMaterial(foodMaterial);
        if (rows > 0) return null ;
        return "新增食材失败" ;
    }

    @Override
    public String modifyFoodMaterial(FoodMaterial foodMaterial) {
        String result = checkFoodMaterialName(foodMaterial) ;
        if (result != null) return result ;
        if (foodMaterial.getOriginalProcess() == false) foodMaterial.setOriginalType(foodMaterial.getId());
        int rows = dao.updateFoodMaterial(foodMaterial);
        if (rows > 0) return null ;
        return "修改食材失败" ;
    }

    @Override
    public int stopFoodMaterial(Map<String,Object> params) {
        return dao.stopFoodMaterial(params);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String batchModifyFoodMaterialPrice(List<FoodMaterial> foodMaterials) {
        if (foodMaterials == null || foodMaterials.isEmpty()) return "请至少设置一条食材价格的修改信息" ;
        BigDecimal bd = new BigDecimal("0.00") ;
        for (FoodMaterial fm : foodMaterials) {
            if (fm.getId() == null || fm.getSalePrice() == null || fm.getSalePrice().compareTo(bd) <= 0) {
                return fm.getName() + "食材价格销售不能为空，并大于0" ;
            }
        }
        int result = dao.batchUpdateFoodMaterialPrice(foodMaterials);
        if (result <= 0) return "没有食材价格的修改信息" ;
        return null ;
    }

    @Override
    public List<FoodMaterial> queryFoodMaterial(FoodMaterialDto dto) {
        return dao.selectFoodMaterial(dto);
    }

    @Override
    public List<FoodMaterial> querySupplyFoodMaterial(FoodMaterialDto dto) {
        return dao.selectSupplyFoodMaterial(dto);
    }

    @Override
    public List<FoodMaterial> queryVipFoodMaterial(FoodMaterialDto dto) {
        return dao.selectVipFoodMaterial(dto);
    }

    @Override
    public List<FoodMaterial> queryVipSupplyFoodMaterial(FoodMaterialDto dto) {
        return dao.selectVipSupplyFoodMaterial(dto);
    }

    private String checkFoodMaterialSupply(FoodMaterialAction.Supply supply) {
        FoodMaterialSupplyDto where = new FoodMaterialSupplyDto() ;
        where.setBeginDate(DateUtil.format(supply.getBeginDate(), Constants.DEFAULT_DATE_FORMAT));
        where.setEndDate(DateUtil.format(supply.getEndDate(),Constants.DEFAULT_DATE_FORMAT));
        where.setIds(supply.getFoodMaterialId());
        int total = dao.checkFoodMaterialSupplyCount(where) ;
        if (total == 0) return null ;
        PageHelper.startPage(1,50) ;
        List<FoodMaterialSupply> list = dao.checkFoodMaterialSupply(where) ;
        Map<String,List<Date>> choice = new HashMap<>() ;
        for (FoodMaterialSupply fms : list) {
            if (choice.containsKey(fms.getFoodMaterialName())) {
                choice.get(fms.getFoodMaterialName()).add(fms.getSupplyDate()) ;
            } else {
                List<Date> list1 = new ArrayList<>();
                list1.add(fms.getSupplyDate()) ;
                choice.put(fms.getFoodMaterialName(),list1) ;
            }
        }
        StringBuilder sb = new StringBuilder() ;
        choice.forEach((k,v) -> {
            sb.append(k).append("：在[") ;
            for (Date date : v) {
                sb.append(this.getDate(date)).append(',');
            }
            sb.deleteCharAt(sb.length() - 1) ;
            sb.append("]已经发布；");
        });
        return sb.toString() ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addFoodMaterialSupply(FoodMaterialAction.Supply supply) {
        String check = checkFoodMaterialSupply(supply) ;
        if (check != null) return check ;
        Date currentDate = DateUtil.parse(this.getCurrentDate()) ;
        if (supply.getBeginDate().before(currentDate)) {
            return "食材供应开始日期要大于等于当前系统日期" ;
        }
        if (supply.getEndDate().getTime() < supply.getBeginDate().getTime()) {
            return "食材供应截至日期要大于等于开始日期" ;
        }
        List<Date> dateList = DateUtil.dateRange(supply.getBeginDate(),supply.getEndDate()) ;

        List<Long> ids = supply.getFoodMaterialId() ;
        List<FoodMaterialSupply> foodMaterialSupplyList = new ArrayList<>();
        for (Long id : ids) {
            for (Date date : dateList) {
                FoodMaterialSupply fms = new FoodMaterialSupply() ;
                fms.setId(nextId());
                fms.setFoodMaterialId(id);
                fms.setSupplyDate(date);
                fms.setOriginalProcess(supply.getOriginalProcess());
                foodMaterialSupplyList.add(fms) ;
            }
        }
        int result = dao.insertFoodMaterialSupply(foodMaterialSupplyList);
        if (result <= 0) return "新增食材供应失败" ;
        return null ;
    }

    @Override
    public String removeFoodMaterialSupply(FoodMaterialSupplyDto dto) {
        if (dto.getBeginDate() == null && dto.getEndDate() == null && dto.getId() == null) return "请输入删除的条件" ;
        if ((dto.getBeginDate() != null && dto.getEndDate() == null) ||
            (dto.getBeginDate() == null && dto.getEndDate() != null)) return "请输入删除的日期范围" ;
        Date end = dto.getEndDate() != null ? DateUtil.parse(dto.getEndDate(),Constants.DEFAULT_DATE_FORMAT) : null ;
        Date begin = dto.getBeginDate() != null ? DateUtil.parse(dto.getBeginDate(),Constants.DEFAULT_DATE_FORMAT) : null;
        if (end != null && begin != null && end.before(begin)) return "截至日期大于等于开始日期";
        if (dto.getId() != null) {
            dto.setBeginDate(null);
            dto.setEndDate(null);
            dto.setFoodMaterialId(null);
        }
        int row =  dao.deleteFoodMaterialSupply(dto);
        if (row <= 0) return "此时间范围没有食材发布信息" ;
        return null ;
    }

    @Override
    public List<FoodMaterialSupply> queryFoodMaterialSupply(FoodMaterialSupplyDto dto) {
        return dao.selectFoodMaterialSupply(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addCustomerPriceTemplate(CustomerPriceTemplate customerPriceTemplate) {
        customerPriceTemplate.setId(nextId());
        for (CustomerPriceTemplateDetail detail : customerPriceTemplate.getDetail()) {
            detail.setId(nextId());
            detail.setTemplateId(customerPriceTemplate.getId());
            detail.setSalePrice(detail.getVipSalePrice());
        }
        dao.insertCustomerPriceTemplate(customerPriceTemplate) ;
        return dao.insertCustomerPriceTemplateDetail(customerPriceTemplate.getDetail());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int modifyCustomerPriceTemplate(CustomerPriceTemplate customerPriceTemplate) {
        dao.updateCustomerPriceTemplate(customerPriceTemplate);
        for (CustomerPriceTemplateDetail detail : customerPriceTemplate.getDetail()) {
            detail.setId(nextId());
            detail.setTemplateId(customerPriceTemplate.getId());
            detail.setSalePrice(detail.getVipSalePrice());
        }
        dao.deleteCustomerPriceTemplateDetail(customerPriceTemplate.getId());
        return dao.insertCustomerPriceTemplateDetail(customerPriceTemplate.getDetail());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeCustomerPriceTemplate(Long templateId) {
        dao.deleteCustomerPriceTemplate(templateId) ;
        return dao.deleteCustomerPriceTemplateDetail(templateId);
    }

    @Override
    public List<CustomerPriceTemplate> queryCustomerPriceTemplate(CustomerPriceTemplate template) {
        return dao.selectCustomerPriceTemplate(template);
    }

    @Override
    public List<CustomerPriceTemplateDetail> queryCustomerPriceTemplateDetail(CustomerPriceTemplateDetailDto dto) {
        return dao.selectCustomerPriceTemplateDetail(dto);
    }

    @Override
    public List<CustomerPriceTemplateDetail> queryCustomerPriceDetail(CustomerPriceDto dto) {
        return dao.selectCustomerPriceDetail(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addCustomerPrice(FoodMaterialAction.CustomerPriceChoice customerPriceChoice) {
        List<CustomerPrice> list = new ArrayList<>() ;
        for (Long customerId : customerPriceChoice.getCustomerIds()) {
            CustomerPrice cp = new CustomerPrice() ;
            cp.setCustomerId(customerId);
            cp.setTemplateId(customerPriceChoice.getTemplateId());
            cp.setOriginalProcess(customerPriceChoice.getOriginalProcess());
            list.add(cp) ;
        }
        CustomerPriceDto dto = new CustomerPriceDto() ;
        dto.setOriginalProcess(customerPriceChoice.getOriginalProcess());
        dto.setCustomerIds(customerPriceChoice.getCustomerIds());
        dao.deleteCustomerPrice(dto);
        return dao.insertCustomerPrice(list);
    }

    @Override
    public int removeCustomerPrice(CustomerPriceDto dto) {
        return dao.deleteCustomerPrice(dto);
    }

    @Override
    public List<CustomerPrice> queryCustomerPrice(CustomerPriceDto dto) {
        List<CustomerPrice> result = dao.selectCustomerPrice(dto) ;
        if (dto.getOriginalProcess() == null && dto.getOnlyRowShow() == null) {//把存在净菜/毛菜模板的放在一条记录上
            Set<Long> set = new HashSet<>() ;
            List<CustomerPrice> temp = new ArrayList<>() ;
            int index = 0;
            for (CustomerPrice cp : result) {
                if (set.contains(cp.getCustomerId())) {
                    CustomerPrice cp1 = temp.get(index++) ;
                    cp1.setTemplateName(cp1.getTemplateName() + "|" + cp.getTemplateName());
                } else {
                    temp.add(cp) ;
                    set.add(cp.getCustomerId()) ;
                }
            }
            result = temp ;
        }
        return result ;
    }

    @Override
    public String clearFoodMaterial() {
        if (dao.checkFoodMaterial() > 0) return "食材信息已经被使用了，不能清理";
        dao.truncateFoodMaterialType();
        dao.truncateFoodMaterial();
        return null;
    }

    @Override
    public int addTestReport(TestReport testReport) {
        testReport.setId(nextId());
        return dao.insertTestReport(testReport);
    }

    @Override
    public int modifyTestReport(TestReport testReport) {
        return dao.updateTestReport(testReport);
    }

    @Override
    public int removeTestReport(Long id) {
        return dao.deleteTestReport(id);
    }

    @Override
    public List<TestReport> queryTestReport(TestReportDto dto) {
        return dao.selectTestReport(dto);
    }

    @Override
    public TestReport queryTestReportById(Long id) {
        TestReportDto dto = new TestReportDto() ;
        dto.setId(id);
        List<TestReport> result = dao.selectTestReport(dto) ;
        return result.size() == 0 ? null : result.get(0);
    }
}
